package com.ruoyi.common.utils.poi;

import cn.hutool.core.bean.BeanUtil;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.policy.HackLoopTableRenderPolicy;
import com.deepoove.poi.util.PoitlIOUtils;
import com.ruoyi.common.enums.DataTypeEnum;
import org.springframework.core.io.ClassPathResource;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class DocumentHandlerUtils {

    public static void exportWord(HttpServletResponse response, Map<String, Object> dataMap, DataTypeEnum fileEnum) {
        InputStream inputStream = null;
        ServletOutputStream out = null;
        BufferedOutputStream bos = null;
        try {
            ClassPathResource classPathResource = new ClassPathResource("./templates/" + fileEnum.getTemplateName());
            inputStream = classPathResource.getInputStream();
            XWPFTemplate template = XWPFTemplate.compile(inputStream).render(dataMap);
            template.write(new FileOutputStream("output.docx"));
            response.setContentType("application/octet-stream");
            response.addHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode(fileEnum.getFileName())
                            + ";filename*=utf-8''" + URLEncoder.encode(fileEnum.getFileName()));
            out = response.getOutputStream();
            bos = new BufferedOutputStream(out);
            template.write(bos);
            bos.flush();
            out.flush();
            PoitlIOUtils.closeQuietlyMulti(template,bos,out);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (null != out) {
                try {
                    //最后别忘记了关闭流
                    out.close();
                } catch (IOException e) {
                }
            }
            if (null != bos) {
                try {
                    //最后别忘记了关闭流
                    bos.close();
                } catch (IOException e) {
                }
            }
            if (null != inputStream) {
                try {
                    //最后别忘记了关闭流
                    inputStream.close();
                } catch (IOException e) {
                }
            }

        }


        /**
         *  1. 获取所有投票人的列表数据
         *    此处使用测试数据，实际项目中需要自己从数据库查询
         * */

//        List<VoteInfo> infoList = new ArrayList<VoteInfo>() {{
//
////            add(new VoteInfo("张三", "1", "没有意见"));
////            add(new VoteInfo("李四", "1", "同意"));
////            add(new VoteInfo("王五", "3", "拒绝，不同意"));
////            add(new VoteInfo("宋小宝", "4", "我回避！不做任何评价"));
////            add(new VoteInfo("海燕", "2", "我认为需要续议，日后再重新讨论"));
//        }};
//
//        StringBuffer allOpinion = new StringBuffer();
//        for (VoteInfo info : infoList) {
//            //拼接所有投票人的意见  并换行
//            allOpinion.append(info.getVoterName() + "：" + info.getVoteOpinion() + "\n");
//        }
//
//        /**
//         *  2. 获取并设置表单数据  此处为测试数据  meetingType和passFlag默认设置为1
//         *  复选框 meetingType  会议类型 1、股东会 2、董事会  3、合伙人会 4、其他
//         *  复选框 passFlag  是否通过 1、同意  2、续议  3、拒绝
//         * */
//
////        DataForm dataForm = new DataForm("程序猿公司", "2024", "1", "1",
////                "程序猿股东大会-如何走向人生巅峰迎娶白富美", "1", "1",
////                allOpinion.toString(), "程序猿", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
//
//
//        /**
//         * 3. 数据map  用于渲染word表单的数据 将表单数据对象存入map中
//         */
////        Map<String, Object> dataMap = BeanUtil.beanToMap(dataForm);
//        //需要循环的表单数据
//        dataMap.put("dataTable", infoList);
//
//        /**
//         * 4. Configure类是该库中的一个配置类，其作用是提供了一些全局的配置选项
//         * (1) useSpringEL() 开启El表达式{{ }}  word模板中的数据就以这个表达式传递数据 例如：{{companyName}};也可以调用buildGramer("${", "}") 可以修改模板为${}
//         * (2) bind()  绑定标记需要循环的数据
//         * (3) 实现表格行循环的策略 HackLoopTableRenderPolicy 不同poi版本实现行循环的策略不一样；当前案例是poi-tl 1.9.1版本
//         *      1.9.x版本：HackLoopTableRenderPolicy  1.10.x以后的版本：LoopRowTableRenderPolicy
//         *
//         */
//        ConfigureBuilder configureBuilder = Configure.builder().useSpringEL().bind("dataTable", new HackLoopTableRenderPolicy());
//        Configure config = configureBuilder.build();
//        InputStream is = null;
//        try {
//            /**
//             *  5. word模板渲染数据  wordForm.docx为模板，本案例放在了项目根目录的wordTemplates下
//             */
//            ClassPathResource classPathResource = new ClassPathResource("./templates/" + fileEnum.getTemplateName());
//
////            is = new ClassPathResource("./templates/yfjsba.docx").getInputStream();
//            is = classPathResource.getInputStream();
//            XWPFTemplate template = XWPFTemplate.compile(is, config).render(dataMap);
//
//            response.setContentType("application/octet-stream");
//            response.addHeader("Content-Disposition",
//                    "attachment;filename=" + URLEncoder.encode("程序猿会议意见反馈表.docx")
//                            + ";filename*=utf-8''" + URLEncoder.encode("程序猿会议意见反馈表.docx"));
//
//            /** 6.  根据模板生成word文件的指定路径 */
////            String filePath = "D:/note/程序猿会议意见反馈表.docx";
//            //生成 意见反馈表word 到指定路径
//
////            OutputStream out = new FileOutputStream(filePath);
//            ServletOutputStream out = response.getOutputStream();
//
//
//            /**  若是直接访问下载打开 可以通过如下方式实现 不需要设置文件路径
//             *  String fileName = URLEncodeUtil.encode("程序猿会议意见反馈表");
//             *  response.setContentType("application/octet-stream;charset=utf-8");
//             *  response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".docx");
//             *  OutputStream out = response.getOutputStream();
//             */
//
//            /**
//             *  7. 文件输出
//             */
//            template.writeAndClose(out);
//            out.flush();
//            PoitlIOUtils.closeQuietlyMulti(template, out);
//        } catch (IOException e) {
//        } finally {
//            if (null != is) {
//                try {
//                    //最后别忘记了关闭流
//                    is.close();
//                } catch (IOException e) {
//                }
//            }
//        }

    }

    public static void test(HttpServletResponse response) {
        /**
         *  1. 获取所有投票人的列表数据
         *    此处使用测试数据，实际项目中需要自己从数据库查询
         * */

        List<VoteInfo> infoList = new ArrayList<VoteInfo>() {{

//            add(new VoteInfo("张三", "1", "没有意见"));
//            add(new VoteInfo("李四", "1", "同意"));
//            add(new VoteInfo("王五", "3", "拒绝，不同意"));
//            add(new VoteInfo("宋小宝", "4", "我回避！不做任何评价"));
//            add(new VoteInfo("海燕", "2", "我认为需要续议，日后再重新讨论"));
        }};

        StringBuffer allOpinion = new StringBuffer();
        for (VoteInfo info : infoList) {
            //拼接所有投票人的意见  并换行
            allOpinion.append(info.getVoterName() + "：" + info.getVoteOpinion() + "\n");
        }

        /**
         *  2. 获取并设置表单数据  此处为测试数据  meetingType和passFlag默认设置为1
         *  复选框 meetingType  会议类型 1、股东会 2、董事会  3、合伙人会 4、其他
         *  复选框 passFlag  是否通过 1、同意  2、续议  3、拒绝
         * */

        DataForm dataForm = new DataForm("程序猿公司", "2024", "1", "1",
                "程序猿股东大会-如何走向人生巅峰迎娶白富美", "1", "1",
                allOpinion.toString(), "程序猿", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));


        /**
         * 3. 数据map  用于渲染word表单的数据 将表单数据对象存入map中
         */
        Map<String, Object> dataMap = BeanUtil.beanToMap(dataForm);
        //需要循环的表单数据
        dataMap.put("dataTable", infoList);

        /**
         * 4. Configure类是该库中的一个配置类，其作用是提供了一些全局的配置选项
         * (1) useSpringEL() 开启El表达式{{ }}  word模板中的数据就以这个表达式传递数据 例如：{{companyName}};也可以调用buildGramer("${", "}") 可以修改模板为${}
         * (2) bind()  绑定标记需要循环的数据
         * (3) 实现表格行循环的策略 HackLoopTableRenderPolicy 不同poi版本实现行循环的策略不一样；当前案例是poi-tl 1.9.1版本
         *      1.9.x版本：HackLoopTableRenderPolicy  1.10.x以后的版本：LoopRowTableRenderPolicy
         *
         */
        ConfigureBuilder configureBuilder = Configure.builder().useSpringEL().bind("dataTable", new HackLoopTableRenderPolicy());
        Configure config = configureBuilder.build();
        InputStream is = null;
        try {
            /**
             *  5. word模板渲染数据  wordForm.docx为模板，本案例放在了项目根目录的wordTemplates下
             */
            is = new ClassPathResource("./templates/wordForm.docx").getInputStream();
            XWPFTemplate template = XWPFTemplate.compile(is, config).render(dataMap);

            response.setContentType("application/octet-stream");
            response.addHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode("程序猿会议意见反馈表.docx")
                            + ";filename*=utf-8''" + URLEncoder.encode("程序猿会议意见反馈表.docx"));

            /** 6.  根据模板生成word文件的指定路径 */
            String filePath = "D:/note/程序猿会议意见反馈表.docx";
            //生成 意见反馈表word 到指定路径

//            OutputStream out = new FileOutputStream(filePath);
            ServletOutputStream out = response.getOutputStream();


            /**  若是直接访问下载打开 可以通过如下方式实现 不需要设置文件路径
             *  String fileName = URLEncodeUtil.encode("程序猿会议意见反馈表");
             *  response.setContentType("application/octet-stream;charset=utf-8");
             *  response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".docx");
             *  OutputStream out = response.getOutputStream();
             */

            /**
             *  7. 文件输出
             */
            template.writeAndClose(out);
            out.flush();
            PoitlIOUtils.closeQuietlyMulti(template, out);
        } catch (IOException e) {
        } finally {
            if (null != is) {
                try {
                    //最后别忘记了关闭流
                    is.close();
                } catch (IOException e) {
                }
            }
        }
    }

}
